import { CustomDataSource, CzmlDataSource, Viewer } from "cesium";
import {
  getViewer,
  ViewerNameType,
  defaultConfig,
  nextTick,
  isString,
} from "yt-cesium";

const entitySourceMap: WeakMap<
  Viewer,
  Map<string, CustomDataSource>
> = new WeakMap();

/**
 * 设置缓存中的
 * @param sourceName
 * @param source
 * @param viewerName
 */
function setEntitySource(
  sourceName: string,
  source: CustomDataSource,
  viewerName: ViewerNameType = getViewer()
) {
  if (isString(viewerName)) {
    viewerName = getViewer(viewerName);
  }
  if (!entitySourceMap.has(viewerName)) {
    entitySourceMap.set(viewerName, new Map());
  }
  entitySourceMap.get(viewerName)!.set(sourceName, source);
}

/**
 * 从缓存中获取
 * @param sourceName
 * @param viewerName
 */
export function getEntitySource(
  sourceName: string,
  viewerName: ViewerNameType = getViewer()
) {
  if (isString(viewerName)) {
    viewerName = getViewer(viewerName);
  }
  return entitySourceMap.get(viewerName)?.get(sourceName);
}

/**
 * 创建source
 * @param sourceName
 * @param viewerName
 */
export function createEntityDatasource(
  sourceName: string,
  viewerName: string = defaultConfig.DEFAULT_VIEWER_NAME
) {
  if (!sourceName) {
    console.warn("请输入 datasource 名称");
    return;
  }
  const source = new CustomDataSource(sourceName);
  setEntitySource(sourceName, source);
  return source;
}

/**
 * 获取source
 * @param sourceName
 * @param viewerName
 */
export function getEntityDatasource(sourceName: string, viewerName?: string) {
  return getEntitySource(sourceName, getViewer(viewerName));
}

/**
 * 清空entitySource
 * @param viewerName
 */
export function clearEntitySourceByViewer(viewerName: string) {
  entitySourceMap.delete(getViewer(viewerName));
}

export function createEntitySource(sourceName: string) {
  let source: CustomDataSource | null = new CustomDataSource(sourceName);
  return {
    source,
    mount: generateMountFn(sourceName, source),
  };
}

/**
 * 生成Datasource挂在函数 mount 高阶函数
 * @param sourceName
 * @param source
 */
export function generateMountFn(
  sourceName: string,
  source: CustomDataSource | CzmlDataSource
) {
  return function (viewerName?: ViewerNameType) {
    if (isString(viewerName)) {
      viewerName = getViewer(viewerName);
    }
    nextTick().then((_viewer: any) => {
      (viewerName ?? _viewer).dataSources.add(source);
      setEntitySource(sourceName, source, viewerName);
    });
  };
}